package com.lvy.hczn.front.system.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lvy.hczn.front.common.constant.Constants;
import com.lvy.hczn.front.common.constant.MqConstants;
import com.lvy.hczn.front.common.constant.RedisConstants;
import com.lvy.hczn.front.common.core.domain.AjaxResult;
import com.lvy.hczn.front.common.core.domain.BaseModel;
import com.lvy.hczn.front.common.core.domain.entity.SysDictData;
import com.lvy.hczn.front.common.core.redis.RedisCache;
import com.lvy.hczn.front.common.exception.UtilException;
import com.lvy.hczn.front.common.utils.DictUtils;
import com.lvy.hczn.front.system.domain.business.*;
import com.lvy.hczn.front.system.domain.system.SysArea;
import com.lvy.hczn.front.system.domain.system.SysAreaCode;
import com.lvy.hczn.front.system.mapper.WarehouseMapper;
import com.lvy.hczn.front.system.service.*;
import com.lvy.hczn.mq.rocket.ParamInfo;
import com.lvy.hczn.mq.rocket.ProducerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class WarehouseServiceImpl extends ServiceImpl<WarehouseMapper, Warehouse> implements WarehouseService {

    @Autowired
    private WarehouseMapper warehouseMapper;

    @Autowired
    private ISysAreaService sysAreaService;

    @Autowired
    private ProducerUtil producerUtil;

    @Autowired
    private SysAreaCodeService sysAreaCodeService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private TemperatureZoneService temperatureZoneService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private GoodsBoxSpecService goodsBoxSpecService;

    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private SpuService spuService;

    @Autowired
    private SkuService skuService;

    /**
     * 获取当前仓库
     *
     * @return
     */
    @Override
    public Warehouse selectLocalWarehouseFront() {
        Warehouse warehouse = redisCache.getCacheObject(RedisConstants.WAREHOUSE_WMS);
        if (warehouse != null) {
            return warehouse;
        } else {
            return super.getOne(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getStatus, Constants.WAREHOUSE_STATUS_ENABLE).orderByDesc(Warehouse::getCreateTime).last("limit 1"));
        }
    }

    @Override
    public List<Warehouse> getPageList(Warehouse warehouse) {
        return warehouseMapper.selectWarehouseList(warehouse);
    }

    @Override
    public synchronized int saveData(Warehouse warehouse, boolean sync) throws Exception {
        if (StrUtil.isEmpty(warehouse.getAreaId())) {
            throw new UtilException("请选择区域");
        }
        Warehouse model = super.getOne(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getStatus, Constants.WAREHOUSE_STATUS_ENABLE).last("limit 1"));
        if (model != null && !StrUtil.isEmpty(model.getId())) {
            throw new UtilException("当前已存在仓库，不可录入");
        }
        SysArea sysArea = sysAreaService.getById(warehouse.getAreaId());
        if (sysArea == null) {
            throw new UtilException("无相关省市区域信息");
        }
        warehouse.setAreaExtId(sysArea.getExtId());
        String warehouseCode = initWarehouseCode(warehouse);
        if (!StrUtil.isEmpty(warehouseCode)) {
            warehouse.setWarehouseCode(warehouseCode);
            if (StrUtil.isEmpty(warehouse.getParentCode())) {
                warehouse.setParentCode(null);
            }
            warehouse.setStatus(Constants.WAREHOUSE_STATUS_ENABLE);
            int row = warehouseMapper.insert(warehouse);

            List<TemperatureZone> temperatureZones = temperatureZoneService.list();
            if (!temperatureZones.isEmpty()) {
                temperatureZones.forEach(temperatureZone -> {
                    temperatureZone.setWarehouseId(warehouse.getId());
                    temperatureZoneService.updateById(temperatureZone);
                });
            }

            if (sync) {
                //发送到数据转发中心的仓库为启用状态
                warehouse.setStatus(Constants.WAREHOUSE_STATUS_ENABLE);
                sendMqMsg(warehouse);
            }

            return row;
        } else {
            return 0;
        }
    }

    /**
     * 生成仓库编号
     *
     * @param warehouseParamInfo
     * @return
     * @author yw
     * @date 2023-05-14 18:02:24
     */
    @Override
    public synchronized String generateWarehouseCode(ParamInfo<Warehouse> warehouseParamInfo) {
        if (warehouseParamInfo.getData() != null && StrUtil.isEmpty(warehouseParamInfo.getData().getAreaExtId())) {
            throw new UtilException("参数为空");
        }
        /*获取选中区域的当前仓库最大编号，没有则聪数据库查询**/
        String lastNum = "";
        SysAreaCode sysAreaCode = sysAreaCodeService.getOne(Wrappers.<SysAreaCode>lambdaQuery().eq(SysAreaCode::getAreaExtId, warehouseParamInfo.getData().getAreaExtId()).orderByDesc(BaseModel::getCreateTime));
        if (sysAreaCode != null) {
            lastNum = sysAreaCode.getCurNumber();
        }
        //平台要求总仓以ZC开头
        String prefix = "";
        if (warehouseParamInfo.getData().getType().equals(Constants.WAREHOUSE_TYPE_WMS)) {
            prefix = MqConstants.WAREHOUSE_PREFIX_ZC;
        } else {
            prefix = MqConstants.WAREHOUSE_PREFIX;
        }
        String result = generateNewNumber(prefix, warehouseParamInfo.getData().getAreaExtId(), lastNum.replaceAll("\\D", ""));
        SysAreaCode areaCode = sysAreaCodeService.getOne(Wrappers.<SysAreaCode>lambdaQuery().eq(SysAreaCode::getAreaExtId, warehouseParamInfo.getData().getAreaExtId()));
        if (areaCode != null) {
            areaCode.setCurNumber(result);
            sysAreaCodeService.updateById(areaCode);
        } else {
            areaCode = new SysAreaCode();
            areaCode.setAreaExtId(warehouseParamInfo.getData().getAreaExtId());
            areaCode.setCurNumber(result);
            sysAreaCodeService.save(areaCode);
        }
        return result;
    }

    @Override
    public int updateData(Warehouse warehouse) throws Exception {
        if (StrUtil.isEmpty(warehouse.getId())) {
            throw new UtilException("ID为空");
        }
        /*if (warehouse.getType().equals(Constants.WAREHOUSE_TYPE_WMS)) {
            warehouse.setParentCode("0");
        }*/
        boolean result = super.updateById(warehouse);
        if (result) {
            LambdaUpdateWrapper<TemperatureZone> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.isNull(TemperatureZone::getWarehouseId).set(TemperatureZone::getWarehouseId, warehouse.getId());
            temperatureZoneService.update(updateWrapper);
//            sendMqMsg(super.getById(warehouse.getId()));
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * 仓库初始化时，同时异步获取基本配置信息
     *
     * @param warehouse
     * @return void
     * @author yw
     * @date 2023-05-20 14:57:29
     */
    @Override
    public void initBaseData(Warehouse warehouse) {
        List<SysDictData> sysDictDataList = DictUtils.getDictCache(Constants.SYNC_COMMON);
        if (!(sysDictDataList != null && !sysDictDataList.isEmpty() && sysDictDataList.get(0).getDictValue().equals("false"))) {
            ThreadUtil.execAsync(() -> {
                List<SysDictData> list = DictUtils.getDictCache(Constants.INTER_TRANSMIT_DICT_TYPE);
                if (list != null && !list.isEmpty()) {
                    String domain = DictUtils.getDictValue(Constants.PLATFORM_DOMAIN, Constants.DATA_TRANSMIT_INTER);
                    for (SysDictData item : list) {
                        if (Constants.TEMPERATURE_ZONE_URL.equals(item.getDictLabel())) {
                            syncTemperatureZoneFromTransmit(item, domain);
                        } else if (Constants.INTER_CATEGORY_URL.equals(item.getDictLabel())) {
                            syncCategoryFromTransmit(item, domain);
                        } else if (Constants.INTER_TRANSMIT_PARENT_WAREHOUSE.equals(item.getDictLabel())) {
                            syncParentListFromTransmit(item, domain);
                        } else if (Constants.INTER_TRANSMIT_GOODS_SPEC.equals(item.getDictLabel())) {
                            syncGoodsSpecFromTransmit(item, domain);
                        } else if (Constants.INTER_SPU_SKU_URL.equals(item.getDictLabel())) {
                            syncSpuFromTransmit(item, domain);
                        }
                    }
                }
            });
        }
    }

    /**
     * 初始化商品sku规格
     *
     * @param sysDictData
     * @param domain
     * @return void
     * @author yw
     * @date 2023-06-28 10:15:16
     */
    public void syncSpuFromTransmit(SysDictData sysDictData, String domain) {
        ParamInfo<Spu> info = new ParamInfo<>();
        String codeResult = HttpRequest.post(domain + sysDictData.getDictValue()).execute().body();
        AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
        if (codeAjaxResult.isSuccess()) {
            String object = JSONUtil.toJsonStr(codeAjaxResult.get(AjaxResult.DATA_TAG));
            List<Spu> list = JSONUtil.toList(object, Spu.class);
            if (list != null && !list.isEmpty()) {
                for (Spu item : list) {
                    Spu spu = spuService.saveOrUpdateSpu(item);
                    List<Sku> skuList = JSON.parseArray(JSON.toJSONString(item.getList()), Sku.class);
                    if (skuList != null && !skuList.isEmpty()) {
                        for (Sku sku : skuList) {
                            sku.setSpuId(spu.getId());
                            sku.setId(sku.getBarcodeId());
                            skuService.saveOrUpdateSku(sku);
                        }
                    }
                }
            }
        }
    }

    /**
     * 货箱规格从数据转发中心获取
     *
     * @param sysDictData
     * @return void
     * @author yw
     * @date 2023-05-25 14:22:41
     */
    public void syncGoodsSpecFromTransmit(SysDictData sysDictData, String domain) {
        ParamInfo<GoodsBoxSpec> info = new ParamInfo<>();
        String codeResult = HttpRequest.post(domain + sysDictData.getDictValue()).body(JSONUtil.toJsonStr(info)).execute().body();
        AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
        if (codeAjaxResult.isSuccess()) {
            String object = JSONUtil.toJsonStr(codeAjaxResult.get(AjaxResult.DATA_TAG));
            List<GoodsBoxSpec> list = JSONUtil.toList(object, GoodsBoxSpec.class);
            if (list != null && !list.isEmpty()) {
                list.forEach(item -> {
                    goodsBoxSpecService.saveOrUpdate(item);
                });
            }
        }
    }

    /**
     * 总仓绑定运营区域
     *
     * @param request
     * @param list
     * @return
     * @author yw
     * @date 2023-05-23 20:06:06
     */
    @Override
    @Transactional
    public void bindingRegionInfo(HttpServletRequest request, List<ParamInfo> list) {
        if (list == null || list.isEmpty()) {
            throw new UtilException("信息为空");
        }
        log.error("bindingRegionInfo:{}", JSONUtil.toJsonStr(list));
        for (ParamInfo info : list) {
            if (StrUtil.hasEmpty(info.getWarehouseCode(), info.getRegionInfoIp())) {
                throw new UtilException("存在空的仓库编号或运营区域编码");
            }
            Warehouse warehouse = super.getOne(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getWarehouseCode, info.getWarehouseCode()).last("limit 1"));
            if (warehouse == null) {
                throw new UtilException(info.getWarehouseCode() + "未获取到仓库信息");
            }
            if (Constants.WAREHOUSE_TYPE_WMS.equals(warehouse.getType())) {
                warehouse.setAreaCode(info.getRegionInfoIp());
                super.updateById(warehouse);
                //前置仓也更新运营区域，目前以运营区域做一个topic，前置仓订阅
                LambdaUpdateWrapper<Warehouse> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(Warehouse::getParentCode, warehouse.getWarehouseCode()).eq(Warehouse::getType, Constants.WAREHOUSE_TYPE_WMS_FRONT).set(Warehouse::getAreaCode, info.getRegionInfoIp());
                super.update(updateWrapper);

                //运营区域放到数据字典
                SysDictData sysDictData = new SysDictData();
                sysDictData.setDictType(Constants.WAREHOUSE_REGION_AREA);
                String region = info.getRegionInfoIp().replace(".", "");
                sysDictData.setDictLabel(region);
                sysDictData.setDictValue(region);
                try {
                    List<SysDictData> sysDictDataList = sysDictDataService.selectDictDataList(sysDictData);
                    if (sysDictDataList.isEmpty()) {
                        sysDictDataService.insertDictData(sysDictData);
                    }
                } catch (Exception e) {
                    throw new RuntimeException("运营区域保存异常");
                }
            } else {
                throw new UtilException(info.getWarehouseCode() + "非有效总仓编号");
            }
        }
    }

    /**
     * 平台修改仓库联系人和电话发送到数据中心
     *
     * @param warehouse
     * @return void
     * @author yw
     * @date 2023-05-25 16:29:25
     */
    @Override
    public void updateByIdFromPlatForm(Warehouse warehouse) {
        if (StrUtil.isEmpty(warehouse.getWarehouseCode())) {
            throw new UtilException("仓库编号为空");
        }
        if (StrUtil.isEmpty(warehouse.getName())) {
            throw new UtilException("联系人为空");
        }
        if (StrUtil.isEmpty(warehouse.getPhone())) {
            throw new UtilException("电话为空");
        }
        Warehouse model = super.getOne(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getWarehouseCode, warehouse.getWarehouseCode()).eq(Warehouse::getStatus, Constants.WAREHOUSE_STATUS_ENABLE));
        if (model == null) {
            throw new UtilException("仓库信息不存在或已停用");
        }
        model.setName(warehouse.getName());
        model.setPhone(warehouse.getPhone());
        if (super.updateById(model)) {
            String topic = this.selectRegionAreaTopic(model);
            String tag = warehouse.getWarehouseCode() + "_" + MqConstants.TOPIC_WAREHOUSE_FROM_TRANSMIT_TAG;
            ParamInfo<Warehouse> info = new ParamInfo<>();
            info.setData(model);
            try {
                //修改的信息从数据中心发送到仓库
                producerUtil.sendAsyncMsg(topic, tag, JSONUtil.toJsonStr(info).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
            } catch (Exception e) {
                throw new UtilException("数据转发异常");
            }
        }
    }

    /**
     * 根据仓库信息找到区域topic生成topic
     *
     * @param warehouse
     * @return java.lang.String
     * @author yw
     * @date 2023-05-25 17:18:43
     */
    @Override
    public String selectRegionAreaTopic(Warehouse warehouse) {
        if (StrUtil.isEmpty(warehouse.getId())) {
            throw new UtilException("请传入仓库信息");
        }
        if (StrUtil.isEmpty(warehouse.getWarehouseCode())) {
            throw new UtilException("仓库编码为空");
        }
        String topic = "";
        //传入的仓库编号为前置仓时，若是前置仓区域为空，则从总仓获取区域作为topic
        if (Constants.WAREHOUSE_TYPE_WMS_FRONT.equals(warehouse.getType())) {
            if (StrUtil.isEmpty(warehouse.getParentCode())) {
                throw new UtilException("仓库未关联总仓");
            }
            if (StrUtil.isEmpty(warehouse.getAreaCode())) {
                //获取当前前置仓仓库信息
                Warehouse wh = super.getOne(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getWarehouseCode, warehouse.getParentCode()).last("limit 1"));
                if (wh == null) {
                    throw new UtilException("无总仓相关信息");
                }
                if (StrUtil.isEmpty(wh.getAreaCode())) {
                    throw new UtilException("总仓未绑定区域");
                }
                topic = MqConstants.TOPIC_WAREHOUSE_AREA + "_" + wh.getAreaCode().replace(".", "");
            } else {
                topic = MqConstants.TOPIC_WAREHOUSE_AREA + "_" + warehouse.getAreaCode().replace(".", "");
            }
        } else {
            if (StrUtil.isEmpty(warehouse.getAreaCode())) {
                throw new UtilException("总仓未关联区域");
            }
            //运营区域编码测试数据为192.168.10.15
            topic = MqConstants.TOPIC_WAREHOUSE_AREA + "_" + warehouse.getAreaCode().replace(".", "");
        }
        return topic;
    }

    @Override
    public void updateToTransmitByTemperatureZoneChanged(TemperatureZone temperatureZone) {
        if (temperatureZone.getTemperAreaVolume() != null && temperatureZone.getTemperAreaVolume().compareTo(BigDecimal.ZERO) >= 0) {
            Warehouse warehouse = this.selectLocalWarehouseFront();
            if (warehouse != null) {
                List<TemperatureZone> sendList = new ArrayList<>();
                List<TemperatureZone> list = temperatureZoneService.list(Wrappers.<TemperatureZone>lambdaQuery().gt(TemperatureZone::getStatus, 0).isNotNull(TemperatureZone::getWarehouseId).isNotNull(TemperatureZone::getTemperAreaVolume));
                BigDecimal total = list.stream().map(TemperatureZone::getTemperAreaVolume).reduce(BigDecimal.ZERO, BigDecimal::add);

                for (TemperatureZone item : list) {
                    if (item.getId().equals(temperatureZone.getId())) {
                        if (item.getTemperAreaVolume() == null) {
                            item.setTemperAreaVolume(BigDecimal.ZERO);
                        }
                        BigDecimal subDecimal = temperatureZone.getTemperAreaVolume().subtract(item.getTemperAreaVolume());
                        if (total.add(subDecimal).compareTo(warehouse.getTotalStorageCount()) == 1) {
                            throw new UtilException("温区库位总和大于总库位,请先在仓库菜单设置仓库总库位");
                        }
                        //修改库位数量时，校验时增加库位还是减少库位，根据类型推送增加或减少到平台
                        BigDecimal sub = temperatureZone.getTemperAreaVolume().subtract(item.getTemperAreaVolume());
                        if (sub.compareTo(BigDecimal.ZERO) != 0) {
                            if (sub.compareTo(BigDecimal.ZERO) == 1) {
                                item.setTemperAreaVolume(sub);
                                sendList.add(item);
                            } else if (sub.compareTo(BigDecimal.ZERO) < 0) {
                                item.setSubtract(true);
                                item.setTemperAreaVolume(sub.abs());
                                sendList.add(item);
                            }
                            temperatureZoneService.updateById(temperatureZone);
                            break;
                        }
                    }
                }
                //数据转发
                if (!sendList.isEmpty()) {
                    warehouse.setList(sendList);
                    ParamInfo<Warehouse> paramInfo = new ParamInfo<>();
                    paramInfo.setData(warehouse);
                    try {
                        producerUtil.sendAsyncMsg(MqConstants.TOPIC_CHANGE_FO_WAREHOUSE, null, JSONUtil.toJsonStr(paramInfo).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
                    } catch (Exception e) {
                        throw new UtilException("数据转发异常");
                    }
                }
            }
        } else {
            temperatureZoneService.updateById(temperatureZone);
        }
    }

    @Override
    public List<Warehouse> parentList(ParamInfo<Warehouse> info) {
        List<Warehouse> list = new ArrayList<>();
        /**测试服务器mysql版本为5.X,暂时这样处理，8以上版本可以getParentNodesByChildNode方法**/
        if (info.getData() == null) {
            list = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getType, Constants.WAREHOUSE_TYPE_WMS));
        } else {
            if (!StrUtil.isEmpty(info.getData().getAreaId())) {
                SysArea area = sysAreaService.getById(info.getData().getAreaId());
                if (area != null && area.getDeep() == 2) {
                    list = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getType, Constants.WAREHOUSE_TYPE_WMS).eq(Warehouse::getAreaId, area.getId()));
                    if (list.isEmpty()) {
                        SysArea city = sysAreaService.getById(area.getPid());
                        if (city != null) {
                            list = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getType, Constants.WAREHOUSE_TYPE_WMS).eq(Warehouse::getCityId, city.getId()));
                            if (list.isEmpty()) {
                                SysArea pro = sysAreaService.getById(city.getPid());
                                if (pro != null) {
                                    list = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getType, Constants.WAREHOUSE_TYPE_WMS).eq(Warehouse::getProvinceId, pro.getId()));
                                }
                            }
                        }
                    }
                }
            } else {
                list = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getType, Constants.WAREHOUSE_TYPE_WMS));
            }
        }
        return list;
    }

    @Override
    public Warehouse bindingSysAreaById(Warehouse warehouse) {
//        warehouse = super.getById(warehouse.getId());
        //测试数据库为5.X,暂时这样处理
        if (warehouse != null && !StrUtil.isEmpty(warehouse.getAreaId())) {
            //区
            SysArea area = sysAreaService.getById(warehouse.getAreaId());
            if (area != null && !StrUtil.isEmpty(area.getPid())) {
                //市
                SysArea city = sysAreaService.getOne(Wrappers.<SysArea>lambdaQuery().eq(BaseModel::getId, area.getPid()));
                if (city != null && !StrUtil.isEmpty(city.getPid())) {
                    warehouse.setCityId(city.getId());
                    SysArea pro = sysAreaService.getOne(Wrappers.<SysArea>lambdaQuery().eq(BaseModel::getId, city.getPid()));
                    if (pro != null) {
                        warehouse.setProvinceId(pro.getId());
                    }
                }
            }
        }
        return warehouse;
    }

    /**
     * 初始化仓库时，需根据区编码和运营区域编码生成基本仓库信息
     * 因为目前设计为：以一个区域为topic，区域下的总仓和前置仓在区域topic下进行的数据监听
     * 即：一个区域topic，负责区域内所有仓库信息交互，
     *
     * @param
     * @return void
     * @author yw
     * @date 2023-05-28 18:24:51
     */
    @Override
    public Warehouse initWarehouse() {
        Warehouse model = super.getOne(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getStatus, Constants.WAREHOUSE_STATUS_ENABLE).last("limit 1"));
        if (model != null) {
            throw new UtilException("仓库已初始化，无需再次初始化");
        }
        List<SysDictData> list = DictUtils.getDictCache(Constants.SYS_DICT_WAREHOUSE_INIT);
        if (list != null && !list.isEmpty()) {
            Map<String, SysDictData> map = list.stream().collect(Collectors.toMap(SysDictData::getDictLabel, Function.identity(), (key1, key2) -> key2));
            if (!map.containsKey(Constants.SYS_DICT_WAREHOUSE_INIT_WAREHOUSE_AREA)) {
                throw new UtilException("初始化仓库时未配置区参数");
            }

            if (!map.containsKey(Constants.SYS_DICT_WAREHOUSE_INIT_WAREHOUSE_REGION_CODE)) {
                throw new UtilException("初始化仓库时未配置仓库运营区域编码");
            }

            if (!map.containsKey(Constants.SYS_DICT_WAREHOUSE_INIT_WAREHOUSE_TYPE)) {
                throw new UtilException("初始化仓库时未配置仓库类型");
            }
            Warehouse warehouse = new Warehouse();
            warehouse.setAreaId(String.valueOf(map.get(Constants.SYS_DICT_WAREHOUSE_INIT_WAREHOUSE_AREA).getDictValue()));
            warehouse.setAreaCode(String.valueOf(map.get(Constants.SYS_DICT_WAREHOUSE_INIT_WAREHOUSE_REGION_CODE).getDictValue()));
            warehouse.setType(String.valueOf(map.get(Constants.SYS_DICT_WAREHOUSE_INIT_WAREHOUSE_TYPE).getDictValue()));
            warehouse.setParentCode("0");
            warehouse.setTotalStorageCount(BigDecimal.ZERO);
            this.bindingSysAreaById(warehouse);
            try {
                int result = this.saveData(warehouse, false);
                if (result == 0) {
                    throw new UtilException("获取仓库编码失败");
                } else {
                    redisCache.set(RedisConstants.WAREHOUSE_WMS, warehouse);
                    this.initBaseData(null);
                }
            } catch (Exception e) {
                log.error("initWarehouse：初始化仓库失败", e);
                if (e instanceof UtilException) {
                    throw new UtilException(e.getMessage());
                } else {
                    throw new UtilException("初始化仓库失败");
                }
            }
        } else {
            throw new UtilException("初始化仓库时未配置数据字典参数");
        }
        return null;
    }

    /**
     * 从数据传输中心同步温区到本地仓库
     *
     * @param sysDictData
     * @return void
     * @author yw
     * @date 2023-05-20 15:11:54
     */
    public void syncTemperatureZoneFromTransmit(SysDictData sysDictData, String domain) {
        String codeResult = HttpRequest.post(domain + sysDictData.getDictValue()).execute().body();
        AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
        if (codeAjaxResult.isSuccess()) {
            String object = JSONUtil.toJsonStr(codeAjaxResult.get(AjaxResult.DATA_TAG));
            List<TemperatureZone> list = JSONUtil.toList(object, TemperatureZone.class);
            if (list != null && !list.isEmpty()) {
                list.forEach(item -> {
                    temperatureZoneService.saveOrUpdate(item);
                });
            }
        }
    }

    /**
     * 从数据传输中心同步总仓到本地仓库
     *
     * @param sysDictData
     * @return void
     * @author yw
     * @date 2023-05-20 15:11:54
     */
    public void syncParentListFromTransmit(SysDictData sysDictData, String domain) {
        Warehouse warehouse = this.selectLocalWarehouseFront();
        ParamInfo<Warehouse> info = new ParamInfo<Warehouse>();
        if (warehouse != null) {
            if (info.getData() == null) {
                info.setData(new Warehouse());
            }
            info.getData().setAreaId(warehouse.getAreaId());
        }
        String param = JSONUtil.toJsonStr(info);
        String codeResult = HttpRequest.post(domain + sysDictData.getDictValue()).body(param).execute().body();
        AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
        if (codeAjaxResult.isSuccess()) {
            redisCache.del(RedisConstants.WAREHOUSE_PARENT_LIST);
            String object = JSONUtil.toJsonStr(codeAjaxResult.get(AjaxResult.DATA_TAG));
            List<Warehouse> list = JSONUtil.toList(object, Warehouse.class);
            if (list != null && !list.isEmpty()) {
                if (warehouse != null) {
                    for (Warehouse model : list) {
                        if (!StrUtil.isEmpty(model.getAreaCode()) && !StrUtil.isEmpty(warehouse.getParentCode()) && model.getWarehouseCode().equals(warehouse.getParentCode())) {
                            warehouse.setAreaCode(model.getAreaCode());
                            super.updateById(warehouse);
                        }
                    }
                }

                redisCache.setCacheList(RedisConstants.WAREHOUSE_PARENT_LIST, list);
                redisCache.expire(RedisConstants.WAREHOUSE_PARENT_LIST, 7, TimeUnit.DAYS);
            }
        }
    }

    /**
     * 从数据传输中心同步分类到本地仓库
     *
     * @param sysDictData
     * @return void
     * @author yw
     * @date 2023-05-20 15:11:54
     */
    public void syncCategoryFromTransmit(SysDictData sysDictData, String domain) {
        String codeResult = HttpRequest.post(domain + sysDictData.getDictValue()).execute().body();
        AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
        if (codeAjaxResult.isSuccess()) {
            String object = JSONUtil.toJsonStr(codeAjaxResult.get(AjaxResult.DATA_TAG));
            List<Category> list = JSONUtil.toList(object, Category.class);
            if (list != null && !list.isEmpty()) {
                list.forEach(item -> {
                    categoryService.saveOrUpdate(item);
                });
            }
        }
    }

    /**
     * 仓库初始化时，同步到平台端
     *
     * @param warehouse
     * @return void
     * @author yw
     * @date 2023-05-20 14:56:04
     */
    public void sendMqMsg(Warehouse warehouse) throws Exception {

        ParamInfo<Warehouse> paramInfo = new ParamInfo<>();
        List<TemperatureZone> list = temperatureZoneService.list(Wrappers.<TemperatureZone>lambdaQuery().eq(TemperatureZone::getWarehouseId, warehouse.getId()).gt(TemperatureZone::getStatus, 0));
        if (!list.isEmpty()) {
            warehouse.setList(list);
        }
        paramInfo.setData(warehouse);
        producerUtil.sendMsg(MqConstants.TOPIC_CHANGE_FO_WAREHOUSE, null, JSONUtil.toJsonStr(paramInfo).getBytes(StandardCharsets.UTF_8), IdUtil.fastSimpleUUID());
    }

    /**
     * 递增编号
     *
     * @param prefixType 前缀
     * @param param      中间参数
     * @param curNumber  当前编号，在当前编号基础上+1
     * @return java.lang.String
     * @author yw
     * @date 2023-05-14 18:10:40
     */
    public synchronized String generateNewNumber(String prefixType, String param, String curNumber) {
        // 默认一个初始设备编号
        if (StrUtil.isEmpty(curNumber)) {
            curNumber = "00001";
        }
        int length = curNumber.length();
        if (length > 5) {
            curNumber = curNumber.substring(length - 5);
        }
        String newEquipmentNo = prefixType + param + curNumber;
        // 判断传入的设备类型与最新设备编号不为空
        if (!curNumber.isEmpty()) {
            // 字符串数字解析为整数
//            int no = Integer.parseInt(curNumber);
            BigInteger no = new BigInteger(curNumber);
            // 最新设备编号自增1
            BigInteger newEquipment = no.add(BigInteger.ONE);
            redisCache.set(param, newEquipment);
            // 将整数格式化为5位数字
            newEquipmentNo = String.format(prefixType + param + "%05d", newEquipment);
        }

        return newEquipmentNo;
    }

    /**
     * 获取数据字典配置的信息，从数据中心获取仓库编号
     * 理论上只有新建仓库，初始化仓库的时候用到一次，不保存token
     * 1.登录数据中心
     * 2.获取仓库编号
     *
     * @param warehouse
     * @return java.lang.String
     * @author yw
     * @date 2023-05-14 15:08:23
     */
    public String initWarehouseCode(Warehouse warehouse) {
        List<SysDictData> list = DictUtils.getDictCache(Constants.INTER_TRANSMIT_DICT_TYPE);
        if (list != null && !list.isEmpty()) {
            String url = "";
            String username = "";
            String password = "";
            String warehouseCodeUrl = "";
            for (SysDictData sysDictData : list) {
                if (sysDictData.getDictLabel().equals(Constants.INTER_URL)) {
                    url = sysDictData.getDictValue();
                } else if (sysDictData.getDictLabel().equals(Constants.INTER_USERNAME)) {
                    username = sysDictData.getDictValue();
                } else if (sysDictData.getDictLabel().equals(Constants.INTER_PASSWORD)) {
                    password = sysDictData.getDictValue();
                } else if (sysDictData.getDictLabel().equals(Constants.INTER_WAREHOUSE_CODE_URL)) {
                    warehouseCodeUrl = sysDictData.getDictValue();
                }
            }
            String domain = DictUtils.getDictValue(Constants.PLATFORM_DOMAIN, Constants.DATA_TRANSMIT_INTER);
            ParamInfo paramInfo = new ParamInfo();
            paramInfo.setData(warehouse);
            String codeResult = HttpRequest.post(domain + warehouseCodeUrl).body(JSONUtil.toJsonStr(paramInfo)).execute().body();
            AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
            if (codeAjaxResult.isSuccess()) {
                String warehouseCode = String.valueOf(codeAjaxResult.get(AjaxResult.DATA_TAG));
                if (!StrUtil.isEmpty(warehouseCode)) {
                    List<Warehouse> listInfo = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getWarehouseCode, warehouseCode));
                    if (listInfo.isEmpty()) {
                        return warehouseCode;
                    }
                } else {
                    throw new UtilException("编号为空");
                }
            } else {
                throw new UtilException(String.valueOf(codeAjaxResult.get(AjaxResult.MSG_TAG)));
            }
            /*if (!StrUtil.hasEmpty(url, username, password, warehouseCodeUrl)) {
                Map<String, Object> map = new HashMap<>();
                map.put(Constants.INTER_USERNAME, username);
                map.put(Constants.INTER_PASSWORD, password);
                String result = HttpRequest.post(url).form(map).execute().body();
                AjaxResult ajaxResult = JSONUtil.toBean(result, AjaxResult.class);
                //理论上只有新建仓库，初始化仓库的时候用到一次，不保存token
                if (ajaxResult.isSuccess() && ajaxResult.containsKey(Constants.AUTH_TOKEN)) {
                    ParamInfo paramInfo = new ParamInfo();
                    paramInfo.setData(warehouse);
                    String codeResult = HttpRequest.post(warehouseCodeUrl).header(Constants.AUTH_TOKEN, ajaxResult.get(Constants.AUTH_TOKEN).toString()).body(JSONUtil.toJsonStr(paramInfo)).execute().body();
                    AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
                    if (codeAjaxResult.isSuccess()) {
                        String warehouseCode = String.valueOf(codeAjaxResult.get(AjaxResult.DATA_TAG));
                        if (!StrUtil.isEmpty(warehouseCode)) {
                            List<Warehouse> listInfo = super.list(Wrappers.<Warehouse>lambdaQuery().eq(Warehouse::getWarehouseCode, warehouseCode));
                            if (listInfo.isEmpty()) {
                                return warehouseCode;
                            }
                        } else {
                            throw new UtilException("编号为空");
                        }
                    } else {
                        throw new UtilException(String.valueOf(codeAjaxResult.get(AjaxResult.MSG_TAG)));
                    }
                } else {
                    throw new UtilException(String.valueOf(ajaxResult.get(AjaxResult.MSG_TAG)));
                }
            }*/
        }
        return null;
    }

    public static void main(String[] args) {
        /*Map<String, Object> map = new HashMap<>();
        map.put("username", "lvyuangou");
        map.put("password", "lvyuangou001!");
        String result = HttpRequest.post("http://localhost:8091/jwt/login").form(map).execute().body();
        AjaxResult ajaxResult = JSONUtil.toBean(result, AjaxResult.class);
        if (ajaxResult.isSuccess() && ajaxResult.containsKey(Constants.AUTH_TOKEN)) {
            Warehouse warehouse = new Warehouse();
            warehouse.setProvinceId("43");
            warehouse.setCityId("4302");
            warehouse.setAreaId("430281");
            warehouse.setAreaExtId("430281000000");
            ParamInfo paramInfo = new ParamInfo();
            paramInfo.setData(warehouse);
            String codeResult = HttpRequest.post("http://localhost:8091/api/dt/index/wh/code").header(Constants.AUTH_TOKEN, ajaxResult.get(Constants.AUTH_TOKEN).toString()).body(JSONUtil.toJsonStr(paramInfo)).execute().body();
            AjaxResult codeAjaxResult = JSONUtil.toBean(codeResult, AjaxResult.class);
            if (codeAjaxResult.isSuccess()) {
                System.out.println(codeAjaxResult.toString());
            }
        }
        System.out.println(ajaxResult.toString());*/

//        String result = generateNewNumber("WH", "430281000000", "00001");
//        System.out.println(result);
    }
}